Online documentation - WebsydianExpress v3.5 |
Version 3.5 of WebsydianExpress introduces significant changes to the validation patterns. This document is not relevant for earlier versions.
The validation is still done based on the definitions in the Plex model, but where earlier versions used the standard meta validation functions provided by Plex, in the new version, we have ported the code in the meta functions to a new abstract function (ValidationShellForProcess). This has allowed us to introduce options for customizing the validation and its output.
The messages from the validation can be implemented either using message log messages or by using text messages. This means that language support are also available for these messages.
This section introduces the basic validation functionality that is implemented in the abstract ValidationShell function.
When using functions that inherit from ValidationShellForProcess you must have the WebsydianExpress runtime and database available.
The validation is performed for one variable, which is defined when implementing the function that inherits from the ValidationShellForProcess function. This variable can be an input, local, or output variable.
The subroutine that performs the validation is the "Main system validation" subroutine. This subroutine must be called after the values of the variable has been populated. Note that the abstract function does not call this subroutine. You have to do this yourself in the function that inherits from ValidationShellForProcess - or the validation will not be performed.
ValidationShellForProcess basically performs 4 different validations - all are based on the standard Plex validation functions with minor modifications:
Field validated by
This validation is performed in the subroutine "Check field validated by".
The validation ensures that all the validation functions for the fields in the validation variable are called.
This validation is performed for all fields irrespective of whether they have been added to the variable by a view or as single fields. Fields that has been omitted from a view that has been added to the validation variable will not be handled.
Field relation validation
This validation is performed in the subroutine "Check field relations".
This checks the optionality restrictions from the the ENT known by FLD /ENT has FLD triples for the views that has been added to the validation variable.
This also calls any validation functions that has been defined for these triples.
Entity relation validation
This validation is performed in the subroutine "Check entity relations".
This checks the optionality for any ENT refers to ENT, ENT associated with ENT, ENT owned by ENT triples for the views that has been added to the validation variable.
This also calls any validation functions that has been defined for these triples
View validated by
This validation is performed in the subroutine "Check view validated by".
This calls any view validation functions defined for the views that has been added to the validation variable.
When an error has been registered, the function will create a message text and write it to the field Environment<*Message text>.
Depending on the function option UseMessageLog, this text will either be created as a message log message or as a message text.
If the message is written to the message log, the resulting message is added as a child to a main message that after the validation will scope all the messages reported by the validation. This is especially useful if you want to create a server function that can perform the validation and report all of the errors back to the calling function.
For each message that relates directly to one specific field (field validated by, field relation validation), the implementation name of the field will be added as a property to the message.
If the message is not written to the message log, the the subroutine "Send message is called.
Afterwards, the validation will proceed. The base behavior of the function is to perform all validations - irrespective of the result of the previous validations. In this way, the function is able to report all errors at once.
After the validation has been performed, the field Environment<*Validation> contains the result of the validation.
This can be accessed in the edit point Handle system validation result - or at any time after the call to the "Main system validation" subroutine.
Note that if the option UseMessageLog is set, all the messages will be found in the message log. The messages will have the category "Validation" and the level "Informative". This means that you can use the message log to diagnose the errors encountered by the users.
One of the important aims of refactoring the validation patterns has been to make the validation more customizable. An important part of this has been to remove the validation from meta functions so that it has been possible to add edit points to the validation.
In all places, where a message has been created and written to Environment<*Message text>, an edit point has been added so that you can do any customizing or overriding of the messages you need in the exact spot where the error has been encountered.
Note that the message log / message texts are in fact created in this edit point (as this is an abstraction that builds on a very basic ValidationShell in the WSYVAL library).
Just before all calls to the Send message subroutine an edit point has been added. In this way, you can add your own handling/storing of specific messages at the point where they are reported.
To make it easier to customize the functionality - and to build other abstract functions based on the ValidationShell, a number of options has been introduced.
These options are set or removed by FNC option NME triples.
Default: Yes
If this option is set to No, the FLD validated by FNC triples will not be handled.
Default: Yes
If this option is set to No, the optionality of the ENT has FLD / ENT known by FLD triples will not be checked.
Default: Yes
If this option is set to No, the ENT has FLD / ENT known by FLD validation functions will not be called.
Default: Yes
If this option is set to No, the ENT refers to ENT / ENT associated with ENT / ENT owned by ENT triples will not be validated.
Default: Yes
If this option is set to No, the VW validated by FNC triples will not be handled.
Default: Yes
If this option is set to No, the Send message subroutine will not be called. This means that you will have to take control of storing and reporting the errors.
This option is mostly meant for use in other abstract functions.
Default: Yes
If this option is set to No, the messages will not be written to the message log. Instead, the messages will be created as message texts.
The text of the message log messages / message texts can be maintained using the administration interface (Language support → Texts and messages).
Note that the message wont be available until it has been thrown the first time.
The message log messages used by the ValidationShellForProcess can be found scoped by the functions WSYAPI/SystemAPI.ValidationMessages and WSYAPI/SystemAPI.ValidationTexts. You can change the messages by creating your own functions and replace the relevant CreateLogMessage / CreateTextMessage function on the function that inherits from ValidationShellForProcess. Unless you need to add parameters to the message, you should just change the text of the existing message using the administration interface instead.
Source Object | Verb | Target Object |
---|---|---|
MyFunction | is a FNC | WSYAPI/ValidationShellForProcess |
In the subroutine "Main system validation" - edit point "Set +ValidationVariable":
Define the variable you want to validate and assign it to the meta variable +ValidationVariable.
Example (this function will validate the content of MyVariable):
+++Define Variable: MyVariable
+++Set Value Field: +ValidationVariable, Variable: MyVariable
In the point in your function where you want to perform the validation, call the validation subroutine. This must be done after content of the variable has been populated.
Go Sub Main system validation
You can access the result of the validation in the field Environment<*Validation>. This field will be available in the subroutine "Main system validation" - edit point "Handle system validation result".
This is the existing EventHandlerForProcess, but inheritance from ValidationShellForProcess has been added.
The default behavior of the EventHandlerForProcess will be to use the old validation - as anything else would mean that all existing functions would have to be retested when upgrading to this version.
By setting the option UseNewValidation, you can instruct the EventHandler to use the new validation.
The function will validate the content of the Webinput variable. The default behavior is to validate all fields in the Webinput variable, but by setting the option ValidateHiddenFields to No, you can ensure that the fields specific validation isn't performed for these fields.
This is based on the ValidationShellForProcess function. The functionality is the same as the one described above, with the following changes.
The validation variable is set to WebInput
The "Main system validation" subroutine is called from the existing "Field and relation validation" subroutine. This will only be called if the UseNewValidation option is set.
If you have undefined the "Field and relation validation" subroutine to avoid the existing validation, this call will not be made.
In addition to the options defined for the ValidationShellForProcess function, the following options are available:
Default: No
When this is No, the options CheckFldValidatedBy, CheckFldOptionality, CheckFldRelationValidatedBy, CheckEntityRelations. CheckViewValidatedBy are automatically set to No. This means that no code will be generated for the new validation.
Set this option to use the new validation functionality and to disable the old.
Default: Yes
Set this to No if you do not want to validate the hidden fields (the fields in the local variable Hidden). Note that this will only influence the field related validation - not the relation and view validation.
Default: No
Unless this is set to Yes, no validation (new or old) will be performed.
This is an option that has been introduced in an earlier version.
Source Object | Verb | Target Object |
---|---|---|
MyFunction | is a FNC | WSYAPI/EventHandlerForProcess |
MyFunction | option NME
...value SYS |
UseNewValidation
Yes |
The EventHandlerForProcess is an existing abstract function and as such, you should be aware that functionality has been added to the function.
However, the default behavior of the function will not change unless you set the option UseNewValidation.
Unless you want to implement the new validation functionality, you do not have to do anything when upgrading.
In the current implementation of the validation in the Websydian/WebsydianExpress patterns, the validation has always been performed in the EventHandler itself. This has some obvious practical advantages - primarily that the function can use the Send message subroutine to make the messages available for the PageGenerator.
However, having the validation implemented in the EventHandler itself has it owns problems:
1. The validation can only be tested by calling the EventHandler. This means that the web application has to be in place before you can test the validation.
2. When the validation is implemented in the EventHandler itself, it can't be called from other functions (or even from other EventHandlers). This means that you risk having the same validation implemented in many different functions - even if all the validation is made by using the Plex definitions, the question of when each function has been generated and built means that the different functions can perform different validation.
3. Each check performed in the validation can in some variants mean that a connection is made from the application server (the server where the EventHandler is deployed) to the database server. In the cases, where this is not the same server, this can carry a significant overhead.
This section describes the abstract functions that can help you developing validation functions for your application and how to ensure that they are called in your EventHandlers.
This is the EventHandler you should inherit from when you want to implement an EventHandler that uses a separate validation function.
The option ValidationEnabled is set to No (as the validation should not be performed in the EventHandler itself).
The function calls a function WSYAPI/Abstract.ValidationFunction in the edit point Process Input. To create your own validation function, let it inherit from the abstract function and replace the function on the EventHandler.
This is the function that will be used to perform the validation. The function has an input variable WebInputData. The function will validate the content of this variable.
If any errors has been found, the function will return an error code in the returning status. This error codes specifies a message in the message log. The messages thrown by the validation will be found as child messages to this message.
Note that the TransactionValidation function doesn't inherit from WSYAPI/Abstract.WebServerExternal - this is because you in some cases might want to split the validation out in a separate function - but still let it be executed on the server where you run the EventHandler/PageGenerators (this is always a necessity if you have the WebsydianExpress database and the application database on separate servers).
This is only relevant if you have UseMessageLog set to Yes (default) for the validation function.
In some cases, you will define functions that will be called as part of the validation - e.g. the functions specified by FLD validated by FNC / VW validated by FNC.
The "normal" validation functions will just return *Error in the returned status. The reaction of the calling function is to create a generic message that just states that there is something wrong with the field.
By using the message log to store the validation messages you get the option to create specific messages for each error situation in the validated by functions and to report them back to the calling function, which will in this case not create a generic error message it will just add the reported message to the main validation message.
This example will show how you can create a server side validation function for an entity MyEntity and an EventHandler that calls this validation function.
Source Object | Verb | Target Object |
---|---|---|
MyValidationFunction | is a FNC | WSYAPI/Abstract.ValidationFunction |
MyValidationFunction | input view VW
...for VAR |
MyEntity.Update
WebInputData |
MyValidationFunction | implement SYS | Yes |
Source Object | Verb | Target Object |
---|---|---|
MyEventHandler | is a FNC | WSYAPI/Abstract.EventHandlerValidationFunction |
MyEventHandler | local view VW
...for VAR |
MyEntity.Update
WebInput |
MyEventHandler | replaces FNC
...by FNC |
WSYAPI/Abstract.ValidationFunction
MyValidationFunction |
MyEventHandler | implement SYS | Yes |
The default behavior of the validation function is to use the message log as a store for the messages reported by the validation and that the error page specified for the EventHandler is called if the validation reports an error. If this is the behavior you want, you do not have to do anything else to implement the validation.
The following information is relevant if you want to have your own handling of the result of the validation.
MyValidationFunction has two dual fields: MainMessageID and InstanceValid.
After the call, the MainMessageID will contain the identification of the error message that scopes the messages reported by the validation.
The InstanceValid field indicates whether the validation has been successful. Note that this field is mapped with the local field WsyBase<InstanceValid>, which is used to determine the behavior of the EventHandler after the validation has been performed.
For each error situation you want to handle in the function, create a function:
MyLogMessage is a WSYAPI/Abstract.CreateValidationLogMessage
Create the validated by function as usual.
When you encounter an error in the validated by function, call the appropriate log message function. Set the Environment<*Returning status> to the message id returned by the log message function.
The calling validation function will check whether the value in the returned status is a message id - if it is it will add the message to the main message for the validation.
The normal validation functions just return error or success, as described just above, you can use the message log to return a more specific message about the error - with one extra step you also have the capability to let the validation function return a set of messages.
To do so, you will have to create one more function that inherits from WSYAPI/Abstract.CreateValidationLogMessage. Just as the calling validation function has a main message to which all the relevant messages for the validation are added as child messages, this message will be the main message for the validated by function.
Specify a message like "Error from validation of field &(1:)" in the message text for this message. When you encounter the first error in the validation function, start by calling this message and assign the value returned by it to the Environment<*Returning status> field.
Then call the relevant log message function for the specific error and add it as a child to this message.
For each error encountered afterwards, just add the resulting message as s child.
In the end the validation function will return a message that contain a number of messages, this message will be added to the main message of the validation function. In this way a tree-structure with three levels will be created.
The normal behavior of the error pages has been that the EventHandler has written the messages to memory, the PageGenerator is called by the EventHandler and so it can read the messages from memory and show them in a gird.
As the default for the new validation is that the messages are stored as WebsydianExpress message log messages, functionality to show these messages has been added to the existing WebsydianExpress error pages.
The identification of the main WebsydianExpress message (that scopes all the messages from the validation) is written to memory by the EventHandler. The information is read by the PageGenerator (it populates the local field InputByMemory<APIFields.MainMessageID>). After reading and showing all the "old" style messages from memory, all child messages for the main messages are read and shown in the grid.
So in this way, all messages are shown, no matter which method has been used to transfer them from the EventHandler to the error page.
This function can be used as the ancestor of any custom validation log messages you want to create. The messages will get the level "Informative" and the message category "Validation".
This function can be used as the ancestor of any custom validation text messages you want to create. The message types will get the category "Validation".